package com.iwhalecloud.citybrain.flow.platform.manager.application.service.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.iwhalecloud.citybrain.flow.platform.manager.application.common.enums.FormFieldLimitEnum;
import com.iwhalecloud.citybrain.flow.platform.manager.application.utils.BeanCopierUtils;
import com.iwhalecloud.citybrain.flow.platform.manager.application.utils.JsonUtils;
import com.iwhalecloud.citybrain.flow.platform.manager.common.ConstanceVariable;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.form.FormFieldDTO;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.form.FormFieldLimitDomain;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowFormRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author: liyang
 * @date: 2021/10/9 17:18
 */
@Slf4j
@Component
public class SaveFormFieldLimitAbstractProcessor {

    @Autowired
    private FlowFormRepository flowFormRepository;

    protected void saveFormField(JsonNode modelJson,String deployId,String formType){
        JsonNode modelProperties = modelJson.get("properties");
        if (Objects.nonNull(modelProperties)){
            JsonNode formFieldNode = modelProperties.get(ConstanceVariable.FORM_FIELDS);

            if (Objects.nonNull(formFieldNode)){
                String formId = modelProperties.get(ConstanceVariable.FORM_ID).textValue();
                String code = "";
                //0：全局表单，1：节点表单
                if (Objects.equals("0",formType)){
                    code = modelProperties.get(ConstanceVariable.PROCESS_ID).textValue();
                }else if (Objects.equals("1",formType)){
                    code = modelProperties.get(ConstanceVariable.OVERRIDE_ID).textValue();
                }
                if (formFieldNode instanceof ArrayNode){
                    ArrayNode formFieldList = (ArrayNode) formFieldNode;
                    List<FormFieldLimitDomain> formFieldLimitDomainList = new ArrayList<>();
                    for (Object fieldObj : formFieldList) {

                        FormFieldDTO formField = JsonUtils.toObject(JsonUtils.toJson(fieldObj), FormFieldDTO.class);

                        FormFieldLimitDomain formFieldLimitDomain = new FormFieldLimitDomain();
                        BeanCopierUtils.copyProperties(formField,formFieldLimitDomain);
                        formFieldLimitDomain.setDeployId(deployId);
                        formFieldLimitDomain.setFormId(formId);
                        if (Objects.equals("0",formType)){
                            formFieldLimitDomain.setFlowCode(code);
                        }else if (Objects.equals("1",formType)){
                            formFieldLimitDomain.setNodeCode(code);
                        }

                        dealLimitValue(formField,formFieldLimitDomain);

                        formFieldLimitDomainList.add(formFieldLimitDomain);
                    }
                    flowFormRepository.batchInsertFormFieldList(formFieldLimitDomainList);
                }
            }

        }
    }

    protected void dealLimitValue(FormFieldDTO formFieldDTO,FormFieldLimitDomain formFieldLimitDomain){
        int limitValue = 0;
        FormFieldLimitEnum[] fieldLimitEnums = FormFieldLimitEnum.values();
        for (FormFieldLimitEnum fieldLimitEnum : fieldLimitEnums) {
            String code = fieldLimitEnum.getCode();
            try {
                Field field = FormFieldDTO.class.getDeclaredField(code);
                if (Objects.nonNull(field)){
                    field.setAccessible(true);
                    Class fieldType = field.getType();
                    if (Objects.equals(fieldType.getName(),Integer.class.getName()) ){
                        Object valueObj = field.get(formFieldDTO);
                        if (Objects.equals(1,valueObj)){
                            limitValue += 1 << fieldLimitEnum.getBit();
                        }
                    }
                }
            } catch (NoSuchFieldException e) {
                log.error("NoSuchFieldException:",e);
                continue;
            } catch (IllegalAccessException e) {
                log.error("IllegalAccessException:",e);
                continue;
            }
        }
        formFieldLimitDomain.setFieldLimit(limitValue);
    }

}
